home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 24 / AACD 24.iso / AACD / Sound / LAME / WarpOS / src / misc / abx.c next >
Encoding:
C/C++ Source or Header  |  2001-01-25  |  36.5 KB  |  1,259 lines

  1. /* $Id: abx.c,v 1.15 2001/01/25 20:57:40 robert Exp $ */
  2.  
  3. /*
  4.  *  Usage: abx original_file test_file
  5.  *
  6.  *  Ask you as long as the probability is below the given percentage that
  7.  *  you recognize differences
  8.  *
  9.  *  Example: abx music.wav music.mp3
  10.  *           abx music.wav music.mp3 --help
  11.  *
  12.  *  Note: several 'decoding' utilites must be on the 'right' place
  13.  *
  14.  *  Bugs: 
  15.  *      fix path of decoding utilities
  16.  *      only 16 bit support
  17.  *      only support of the same sample frequency
  18.  *      no exact WAV file header analysis
  19.  *      no mouse or joystick support
  20.  *      don't uses functionality of ath.c
  21.  *      only 2 files are comparable
  22.  *      worse user interface
  23.  *      quick & dirty hack
  24.  *      wastes memory
  25.  *      compile time warnings
  26.  *      buffer overruns possible
  27.  *      no dithering if recalcs are necessary
  28.  *      correlation only done with one channel (2 channels, sum, what is better?)
  29.  *      lowpass+highpass filtering (300 Hz+2*5 kHz) before delay+amplitude corr
  30.  *      cross fade at start/stop
  31.  *      non portable keyboard
  32.  *      fade out on quit, fade in on start
  33.  *      level/delay ajustment should be switchable
  34.  *      pause key missing
  35.  *      problems with digital silence files (division by 0)
  36.  *      Größe cross corr fenster 2^16...18
  37.  *      Stellensuche, ab 0*len oder 0.1*len oder 0.25*len, nach Effektiv oder Spitzenwert
  38.  *      Absturz bei LPAC feeding, warum?
  39.  *      Als 'B' beim Ratespiel sollte auch '0'...'9' verwendbar sein 
  40.  *      Kreuzkorrelations mit und ohne Differenzen durchführen?
  41.  *      Oder mit einem Filter 300 Hz...3 kHz vorher filtern?
  42.  *      Maire 12 bit+Noise spaing möchte Originalsignal
  43.  *      Multiple encoded differenziertes Signal
  44.  *      Amplitudenanpassung schaltbar machen?
  45.  *      Direkt auf der Kommandozeile kodieren:
  46.  *      abx "test.wav" "!lame -b128 test.wav -"
  47.  */
  48.  
  49. #if defined(HAVE_CONFIG_H)
  50. # include <config.h>
  51. #endif
  52.  
  53. #include <assert.h>
  54. #include <ctype.h>
  55. #include <fcntl.h>
  56. #include <limits.h>
  57. #include <math.h>
  58. #include <memory.h>
  59. #include <signal.h>
  60. #include <stdio.h>
  61. #include <stdlib.h>
  62. #include <string.h>
  63. #include <termios.h>
  64. #include <time.h>
  65. #include <unistd.h>
  66. #include <sys/ioctl.h>
  67. #include <sys/mman.h>
  68. #include <sys/stat.h>
  69. #include <sys/time.h>
  70. #include <sys/types.h>
  71.  
  72. #define  MAX  (1<<17)
  73.  
  74. #ifdef HAVE_SYS_SOUNDCARD_H
  75. # include <sys/soundcard.h>
  76. #elif defined(HAVE_LINUX_SOUNDCARD_H)
  77. # include <linux/soundcard.h>
  78. #else
  79. # include <linux/soundcard.h>         /* stand alone compilable for my tests */
  80. #endif
  81.  
  82. #define  BF           ((freq)/25)
  83. #define  MAX_LEN      (210 * 44100)
  84. #define  DMA_SAMPLES  512               /* My Linux driver uses a DMA buffer of 65536*16 bit, which is 32768 samples in 16 bit stereo mode */
  85.  
  86. int verbose = 0;
  87.  
  88. static struct termios stored_settings;
  89.  
  90.  
  91. void reset ( void )
  92. {
  93.     tcsetattr ( 0, TCSANOW, &stored_settings );
  94. }
  95.  
  96.  
  97. void set ( void )
  98. {
  99.     struct termios new_settings;
  100.     
  101.     tcgetattr ( 0, &stored_settings );
  102.     new_settings = stored_settings;
  103.     
  104.     new_settings.c_lflag    &= ~ECHO;
  105.     /* Disable canonical mode, and set buffer size to 1 byte */
  106.     new_settings.c_lflag    &= ~ICANON;
  107.     new_settings.c_cc[VTIME] = 0;
  108.     new_settings.c_cc[VMIN]  = 1;
  109.     
  110.     tcsetattr(0,TCSANOW,&new_settings);
  111.     return;
  112. }
  113.  
  114.  
  115. int sel ( void )
  116. {
  117.     struct timeval  t;
  118.     fd_set          fd [1];
  119.     int             ret;
  120.     unsigned char   c;
  121.  
  122.     FD_SET (0, fd);    
  123.     t.tv_sec  = 0;
  124.     t.tv_usec = 0;
  125.  
  126.     ret = select ( 1, fd, NULL, NULL, &t );
  127.     
  128.     switch ( ret ) {
  129.     case  0: 
  130.         return -1;
  131.     case  1: 
  132.         ret = read (0, &c, 1);
  133.         return ret == 1  ?  c  :  -1;
  134.     default: 
  135.         return -2;
  136.     }
  137. }
  138.  
  139. #define FFT_ERR_OK      0               // no error
  140. #define FFT_ERR_LD      1               // len is not a power of 2
  141. #define FFT_ERR_MAX     2               // len too large
  142.  
  143. typedef float   f_t;
  144. typedef f_t     compl [2];
  145. compl           root    [MAX >> 1];             // Sinus-/Kosinustabelle
  146. size_t          shuffle [MAX >> 1] [2];         // Shuffle-Tabelle
  147. size_t          shuffle_len;
  148.  
  149. // Bitinversion
  150.  
  151. size_t  swap ( size_t number, int bits )
  152. {
  153.     size_t  ret;
  154.     for ( ret = 0; bits--; number >>= 1 ) {
  155.         ret = ret + ret + (number & 1);
  156.     }
  157.     return ret;
  158. }
  159.  
  160. // Bestimmen des Logarithmus dualis
  161.  
  162. int  ld ( size_t number )
  163. {
  164.     size_t i;
  165.     for ( i = 0; i < sizeof(size_t)*CHAR_BIT; i++ )
  166.         if ( ((size_t)1 << i) == number )
  167.             return i;
  168.     return -1;
  169. }
  170.  
  171. // Die eigentliche FFT
  172.  
  173. int  fft ( compl* fn, const size_t newlen )
  174. {
  175.     static size_t  len  = 0;
  176.     static int     bits = 0;
  177.     size_t         i;
  178.     size_t         j;
  179.     size_t         k;
  180.     size_t         p;
  181.  
  182.     /* Tabellen initialisieren */
  183.  
  184.     if ( newlen != len ) {
  185.         len  = newlen;
  186.  
  187.         if ( (bits=ld(len)) == -1 )
  188.             return FFT_ERR_LD;
  189.  
  190.         for ( i = 0; i < len; i++ ) {
  191.             j = swap ( i, bits );
  192.             if ( i < j ) {
  193.                 shuffle [shuffle_len] [0] = i;
  194.                 shuffle [shuffle_len] [1] = j;
  195.                 shuffle_len++;
  196.             }
  197.         }
  198.         for ( i = 0; i < (len>>1); i++ ) {
  199.             double x = (double) swap ( i+i, bits ) * 2*M_PI/len;
  200.             root [i] [0] = cos (x);
  201.             root [i] [1] = sin (x);
  202.         }
  203.     }
  204.  
  205.     /* Eigentliche Transformation */
  206.  
  207.     p = len >> 1;
  208.     do {
  209.         f_t*  bp = (f_t*) root;
  210.         f_t*  si = (f_t*) fn;
  211.         f_t*  di = (f_t*) fn+p+p;
  212.  
  213.         do {
  214.             k = p;
  215.             do {
  216.                 f_t  mulr = bp[0]*di[0] - bp[1]*di[1];
  217.                 f_t  muli = bp[1]*di[0] + bp[0]*di[1];
  218.  
  219.                 di[0]  = si[0] - mulr;
  220.                 di[1]  = si[1] - muli;
  221.                 si[0] += mulr;
  222.                 si[1] += muli;
  223.  
  224.                 si += 2, di += 2;
  225.             } while ( --k );
  226.             si += p+p, di += p+p, bp += 2;
  227.         } while ( si < &fn[len][0] );
  228.     } while (p >>= 1);
  229.  
  230.     /* Bitinversion */
  231.  
  232.     for ( k = 0; k < shuffle_len; k++ ) {
  233.         f_t  tmp;
  234.         i   = shuffle [k] [0];
  235.         j   = shuffle [k] [1];
  236.         tmp = fn [i][0]; fn [i][0] = fn [j][0]; fn [j][0] = tmp;
  237.         tmp = fn [i][1]; fn [i][1] = fn [j][1]; fn [j][1] = tmp;
  238.     }
  239.  
  240.     return FFT_ERR_OK;
  241. }
  242.  
  243. void  printnumber ( long double x )
  244. {
  245.     unsigned  exp = 0;
  246.     
  247.     if      ( x < 9.999995  ) fprintf ( stderr, "%7.5f",  (double)x );
  248.     else if ( x < 99.99995  ) fprintf ( stderr, "%7.4f",  (double)x );
  249.     else if ( x < 999.9995  ) fprintf ( stderr, "%7.3f",  (double)x );
  250.     else if ( x < 9999.995  ) fprintf ( stderr, "%7.2f",  (double)x );
  251.     else if ( x < 99999.95  ) fprintf ( stderr, "%7.1f",  (double)x );
  252.     else if ( x < 999999.5  ) fprintf ( stderr, "%6.0f.", (double)x );
  253.     else if ( x < 9999999.5 ) fprintf ( stderr, "%7.0f",  (double)x );
  254.     else if ( x < 9.9995e9  ) {
  255.         while ( x >= 9.9995 ) exp++  , x /= 10;
  256.         fprintf ( stderr, "%5.3fe%01u", (double)x, exp );
  257.     } else if ( x < 9.995e99 ) {
  258.         while ( x >= 9.5e6  ) exp+=6 , x /= 1.e6;
  259.         while ( x >= 9.995  ) exp++  , x /= 10;
  260.         fprintf ( stderr, "%4.2fe%02u", (double)x, exp );
  261.     } else if ( x < 9.95e999L ) {
  262.         while ( x >= 9.5e18 ) exp+=18, x /= 1.e18;
  263.         while ( x >= 9.95   ) exp++  , x /= 10;
  264.         fprintf ( stderr, "%3.1fe%03u", (double)x, exp );
  265.     } else {
  266.         while ( x >= 9.5e48 ) exp+=48, x /= 1.e48;
  267.         while ( x >= 9.5    ) exp++  , x /= 10;
  268.         fprintf ( stderr, "%1.0f.e%04u", (double)x, exp );
  269.     }
  270. }
  271.  
  272. double logdual ( long double x )
  273. {
  274.     unsigned exp = 0;
  275.     
  276.     while ( x >= 18446744073709551616. )
  277.         x /= 18446744073709551616., exp += 64;
  278.     while ( x >= 256. )
  279.         x /= 256., exp += 8;
  280.     while ( x >= 2. )
  281.         x /= 2., exp += 1;
  282.     return exp + log (x)/log(2);
  283. }
  284.  
  285. int  random_number ( void )
  286. {
  287.     struct timeval  t;
  288.     unsigned long   val;
  289.  
  290.     gettimeofday ( &t, NULL );
  291.  
  292.     val  = t.tv_sec ^ t.tv_usec ^ rand();
  293.     val ^= val >> 16;
  294.     val ^= val >>  8;
  295.     val ^= val >>  4;
  296.     val ^= val >>  2;
  297.     val ^= val >>  1;
  298.  
  299.     return val & 1;
  300. }
  301.  
  302. long double  prob ( int last, int total )
  303. {
  304.     long double  sum = 0.;
  305.     long double  tmp = 1.;
  306.     int          i;
  307.     int          j   = total;
  308.     
  309.     if ( 2*last == total )
  310.         return 1.;
  311.     if ( 2*last > total )
  312.         last = total - last;
  313.         
  314.     for ( i = 0; i <= last; i++ ) {
  315.         sum += tmp;
  316.         tmp  = tmp * (total-i) / (1+i);
  317.         while ( j > 0  &&  tmp > 1 )
  318.             j--, sum *= 0.5, tmp *= 0.5;
  319.     }
  320.     while ( j > 0 )
  321.         j--, sum *= 0.5;
  322.  
  323.     return 2.*sum;
  324. }
  325.  
  326.  
  327. void  eval ( int right )
  328. {
  329.     static int   count = 0;
  330.     static int   okay  = 0;
  331.     long double  val;
  332.     
  333.     count ++;
  334.     okay  += right;
  335.     
  336.     val    = 1.L / prob ( okay, count );
  337.     
  338.     fprintf (stderr, "   %s %5u/%-5u ", right ? "OK" : "- " , okay, count );
  339.     printnumber (val);
  340.     if ( count > 1 )
  341.         fprintf (stderr, "   %4.2f bit", 0.01 * (int)(logdual(val) / (count-1) * 100.) );
  342.     fprintf ( stderr, "\n" );
  343. }
  344.  
  345.  
  346. typedef signed short  sample_t;
  347. typedef sample_t      mono_t   [1];
  348. typedef sample_t      stereo_t [2];
  349. typedef struct {
  350.     unsigned long       n;
  351.     long double         x;
  352.     long double         x2;
  353.     long double         y;
  354.     long double         y2;
  355.     long double         xy;
  356. } korr_t;
  357.  
  358.  
  359. void  analyze_stereo ( const stereo_t* p1, const stereo_t* p2, size_t len, korr_t* const k )
  360. {
  361.     long double  _x = 0, _x2 = 0, _y = 0, _y2 = 0, _xy = 0;
  362.     double       t1;
  363.     double       t2;
  364.     
  365.     k -> n  += 2*len;
  366.     
  367.     for ( ; len--; p1++, p2++ ) {
  368.         _x  += (t1 = (*p1)[0]); _x2 += t1 * t1;
  369.         _y  += (t2 = (*p2)[0]); _y2 += t2 * t2;
  370.                                 _xy += t1 * t2;
  371.         _x  += (t1 = (*p1)[1]); _x2 += t1 * t1;
  372.         _y  += (t2 = (*p2)[1]); _y2 += t2 * t2;
  373.                                 _xy += t1 * t2;
  374.     }
  375.     
  376.     k -> x  += _x ;
  377.     k -> x2 += _x2;
  378.     k -> y  += _y ;
  379.     k -> y2 += _y2;
  380.     k -> xy += _xy;
  381. }
  382.  
  383. int  sgn ( double x )
  384. {
  385.     if ( x == 0 ) return 0;
  386.     if ( x <  0 ) return -1;
  387.     return +1;
  388. }    
  389.  
  390. long double  report ( const korr_t* const k )
  391. {
  392.     long double  r;
  393.     long double  sx;
  394.     long double  sy;
  395.     long double  x;
  396.     long double  y;
  397.     long double  b;
  398.     
  399.     r  = (k->x2*k->n - k->x*k->x) * (k->y2*k->n - k->y*k->y);
  400.     r  = r  > 0.l  ?  (k->xy*k->n - k->x*k->y) / sqrt (r)  :  1.l;
  401.     sx = k->n > 1  ?  sqrt ( (k->x2 - k->x*k->x/k->n) / (k->n - 1) )  :  0.l;
  402.     sy = k->n > 1  ?  sqrt ( (k->y2 - k->y*k->y/k->n) / (k->n - 1) )  :  0.l;
  403.     x  = k->n > 0  ?  k->x/k->n  :  0.l;
  404.     y  = k->n > 0  ?  k->y/k->n  :  0.l;
  405.     
  406.     b  = sx != 0   ?  sy/sx * sgn(r)  :  0.l;
  407.     if (verbose)
  408.         fprintf ( stderr, "r=%Lf  sx=%Lf  sy=%Lf  x=%Lf  y=%Lf  b=%Lf\n", r, sx, sy, x, y, b );
  409.     return b;
  410. }
  411.  
  412.  
  413. int  feed ( int fd, const stereo_t* p, int len )
  414. {
  415.     write ( fd, p, sizeof(stereo_t) * len );
  416.     return len;
  417. }
  418.  
  419.  
  420. short  round ( double f )
  421. {
  422.     long  x = (long) floor ( f + 0.5 );
  423.     return x == (short)x  ?  (short)x  :  (short) ((x >> 31) ^ 0x7FFF);
  424. }
  425.  
  426.  
  427. int  feed2 ( int fd, const stereo_t* p1, const stereo_t* p2, int len )
  428. {
  429.     stereo_t  tmp [30000];   /* An arbitrary size, hope that no overruns occure */
  430.     int       i;
  431.     
  432.     if (len > sizeof(tmp)/sizeof(*tmp))
  433.         len = sizeof(tmp)/sizeof(*tmp);
  434.     for ( i = 0; i < len; i++ ) {
  435.         double f = cos ( M_PI/2*i/len );
  436.         f *= f;
  437.         tmp [i] [0] = round ( p1 [i] [0] * f + p2 [i] [0] * (1. - f) );
  438.         tmp [i] [1] = round ( p1 [i] [1] * f + p2 [i] [1] * (1. - f) );
  439.     }
  440.  
  441.     write ( fd, tmp, sizeof(stereo_t) * len );
  442.     return len;
  443. }
  444.  
  445.  
  446. int feedfac ( int fd, const stereo_t* p1, const stereo_t* p2, int len, double fac1, double fac2 )
  447. {
  448.     stereo_t  tmp [30000];   /* An arbitrary size, hope that no overruns occure */
  449.     int       i;
  450.     
  451.     if (len > sizeof(tmp)/sizeof(*tmp))
  452.         len = sizeof(tmp)/sizeof(*tmp);
  453.     for ( i = 0; i < len; i++ ) {
  454.         tmp [i] [0] = round ( p1 [i] [0] * fac1 + p2 [i] [0] * fac2 );
  455.         tmp [i] [1] = round ( p1 [i] [1] * fac1 + p2 [i] [1] * fac2 );
  456.     }
  457.  
  458.     write ( fd, tmp, sizeof(stereo_t) * len );
  459.     return len;
  460. }
  461.  
  462.  
  463. void setup ( int fdd, int samples, long freq )
  464. {
  465.     int status, org, arg;
  466.  
  467.     // Nach vorn verschoben
  468.     if ( -1 == (status = ioctl (fdd, SOUND_PCM_SYNC, 0)) )
  469.         perror ("SOUND_PCM_SYNC ioctl failed");
  470.  
  471.     org = arg = 2;
  472.     if ( -1 == (status = ioctl (fdd, SOUND_PCM_WRITE_CHANNELS, &arg)) )
  473.         perror ("SOUND_PCM_WRITE_CHANNELS ioctl failed");
  474.     if (arg != org)
  475.         perror ("unable to set number of channels");
  476.     fprintf (stderr, "%1u*", arg);
  477.  
  478.     org = arg = 16;
  479.     if ( -1 == (status = ioctl (fdd, SOUND_PCM_WRITE_BITS, &arg)) )
  480.         perror ("SOUND_PCM_WRITE_BITS ioctl failed");
  481.     if (arg != org)
  482.         perror ("unable to set sample size");
  483.     fprintf (stderr, "%2u bit ", arg);
  484.  
  485.     org = arg = AFMT_S16_LE;
  486.     if ( -1 == ioctl (fdd, SNDCTL_DSP_SETFMT, &arg) )
  487.         perror ("SNDCTL_DSP_SETFMT ioctl failed");
  488.     if ((arg & org) == 0)
  489.         perror ("unable to set data format");
  490.  
  491.     org = arg = freq;
  492.     if ( -1 == (status = ioctl (fdd, SOUND_PCM_WRITE_RATE, &arg)) )
  493.         perror ("SOUND_PCM_WRITE_WRITE ioctl failed");
  494.     fprintf (stderr, "%5u Hz*%.3f sec\n", arg, (double)samples/arg );
  495.  
  496.     org = arg = DMA_SAMPLES;
  497.     if ( -1 == (status = ioctl (fdd, SNDCTL_DSP_SETFRAGMENT, &arg)) )
  498.         perror ("SNDCTL_DSP_SETFRAGMENT ioctl failed");
  499. }
  500.  
  501.  
  502. void Message ( const char* s, size_t index, long freq, size_t start, size_t stop )
  503. {
  504.     unsigned long  norm_index = 100lu * index / freq;
  505.     unsigned long  norm_start = 100lu * start / freq;
  506.     unsigned long  norm_stop  = 100lu * stop  / freq;
  507.  
  508.     fprintf ( stderr, "\rListening %s  %2lu:%02lu.%02lu  (%1lu:%02lu.%02lu...%1lu:%02lu.%02lu)%*.*s\rListening %s",
  509.               s,
  510.               norm_index / 6000, norm_index / 100 % 60, norm_index % 100,
  511.               norm_start / 6000, norm_start / 100 % 60, norm_start % 100,
  512.               norm_stop  / 6000, norm_stop  / 100 % 60, norm_stop  % 100,
  513.               36 - (int)strlen(s), 36 - (int)strlen(s), "",
  514.               s );
  515.  
  516.     fflush  ( stderr );
  517. }
  518.  
  519.  
  520. size_t  calc_true_index ( size_t index, size_t start, size_t stop )
  521. {
  522.     if ( start >= stop )
  523.         return start;
  524.     while ( index - start < DMA_SAMPLES )
  525.         index += stop - start;
  526.     return index - DMA_SAMPLES;
  527. }
  528.  
  529.  
  530. void testing ( const stereo_t* A, const stereo_t* B, size_t len, long freq )
  531. {
  532.     int     c;
  533.     int     fd    = open ( "/dev/dsp", O_WRONLY );
  534.     int     rnd   = random_number ();   /* Auswahl von X */
  535.     int     state = 0;                  /* derzeitiger Füttungsmodus */
  536.     float   fac1  = 0.5;
  537.     float   fac2  = 0.5;
  538.     size_t  start = 0;
  539.     size_t  stop  = len;
  540.     size_t  index = start;                  /* derzeitiger Offset auf den Audioströmen */
  541.     char    message [80] = "A  ";
  542.  
  543.     setup ( fd, len, freq );
  544.  
  545.     while ( 1 ) {
  546.         c = sel ();
  547.         if ( c == 27 )
  548.             c = sel () + 0x100;
  549.  
  550.         switch ( c ) {
  551.         case 'A' :
  552.         case 'a' :
  553.             strcpy ( message, "A  " );
  554.             if ( state != 0 )
  555.                 state = 2;
  556.             break;
  557.  
  558.         case 0x100+'0' :
  559.         case '0' :
  560.         case 'B' :
  561.         case 'b' :
  562.             strcpy ( message, "  B" );
  563.             if ( state != 1 )
  564.                 state = 3;
  565.             break;
  566.  
  567.         case 'X' :
  568.         case 'x' :
  569.             strcpy ( message, " X " );
  570.             if ( state != rnd )
  571.                 state = rnd + 2;
  572.             break;
  573.  
  574.         case 'm' :
  575.             state = 8;
  576.             break;
  577.  
  578.         case 'M' :
  579.             state = (state & 1) + 4;
  580.             break;
  581.             
  582.         case 'x'&0x1F:
  583.             state = (state & 1) + 6;
  584.             break;
  585.  
  586.         case ' ':
  587.             start = 0;
  588.             stop  = len;
  589.             break;
  590.  
  591.         case 'o'  :
  592.             start = calc_true_index ( index, start, stop);
  593.             break;
  594.         case 'p'  :
  595.             stop  = calc_true_index ( index, start, stop);
  596.             break;
  597.         case 'h'  :
  598.             if ( start > freq/100 )
  599.                 start -= freq/100;
  600.             else
  601.                 start = 0;
  602.             index = start;
  603.             continue;
  604.         case 'j'  :
  605.             if ( start < stop-freq/100 )
  606.                 start += freq/100;
  607.             else
  608.                 start = stop;
  609.             index = start;
  610.             continue;
  611.         case 'k'  :
  612.             if ( stop > start+freq/100 )
  613.                 stop -= freq/100;
  614.             else
  615.                 stop = start;
  616.             continue;
  617.         case 'l'  :
  618.             if ( stop < len-freq/100 )
  619.                 stop += freq/100;
  620.             else
  621.                 stop = len;
  622.             continue;
  623.         case '\n':
  624.             index = start;
  625.             continue;
  626.  
  627.         case 'D'+0x100:
  628.             strcpy ( message, "Difference (+40 dB)" );
  629.             state = 9;
  630.             fac1  = -100.;
  631.             fac2  = +100.;
  632.             break;
  633.  
  634.         case 'd'+0x100:
  635.             strcpy ( message, "Difference (+30 dB)" );
  636.             state = 9;
  637.             fac1  = -32.;
  638.             fac2  = +32.;
  639.             break;
  640.  
  641.         case 'D' & 0x1F :
  642.             strcpy ( message, "Difference (+20 dB)" );
  643.             state = 9;
  644.             fac1  = -10.;
  645.             fac2  = +10.;
  646.             break;
  647.  
  648.         case 'D' :
  649.             strcpy ( message, "Difference (+10 dB)" );
  650.             state = 9;
  651.             fac1  = -3.;
  652.             fac2  = +3.;
  653.             break;
  654.  
  655.         case 'd' :
  656.             strcpy ( message, "Difference (  0 dB)" );
  657.             state = 9;
  658.             fac1  = -1.;
  659.             fac2  = +1.;
  660.             break;
  661.  
  662.         case 0x100+'1' :
  663.         case 0x100+'2' :
  664.         case 0x100+'3' :
  665.         case 0x100+'4' :
  666.         case 0x100+'5' :
  667.         case 0x100+'6' :
  668.         case 0x100+'7' :
  669.         case 0x100+'8' :
  670.         case 0x100+'9' :
  671.             sprintf ( message, "  B (Errors -%c dB)", (char)c );
  672.             state = 9;
  673.             fac2  = pow (10., -0.05*(c-0x100-'0') );
  674.             fac1  = 1. - fac2;
  675.             break;
  676.  
  677.         case '1' :
  678.         case '2' :
  679.         case '3' :
  680.         case '4' :
  681.         case '5' :
  682.         case '6' :
  683.         case '7' :
  684.         case '8' :
  685.         case '9' :
  686.             sprintf ( message, "  B (Errors +%c dB)", c );
  687.             state = 9;
  688.             fac2  = pow (10., 0.05*(c-'0') );
  689.             fac1  = 1. - fac2;
  690.             break;
  691.  
  692.         case 'A' & 0x1F:
  693.             fprintf (stderr, "   Vote for X:=A" );
  694.             eval ( rnd == 0 );
  695.             rnd   = random_number ();
  696.             if ( state == 6  &&  state == 7 )
  697.                 state = 6 + rnd;
  698.             else if ( state != rnd )
  699.                 state = rnd + 2;
  700.             strcpy ( message," X " );
  701.             break;
  702.  
  703.         case 'B' & 0x1F:
  704.             fprintf (stderr, "   Vote for X:=B" );
  705.             eval ( rnd == 1 );
  706.             rnd   = random_number ();
  707.             if ( state == 6  &&  state == 7 )
  708.                 state = 6 + rnd;
  709.             else if ( state != rnd )
  710.                 state = rnd + 2;
  711.             strcpy ( message," X " );
  712.             break;
  713.  
  714.         case -1:
  715.             break;
  716.  
  717.         default:
  718.             fprintf (stderr, "\a" );
  719.             break;
  720.  
  721.         case 'Q':
  722.         case 'q':
  723.             fprintf ( stderr, "\n%-79.79s\r", "Quit program" );
  724.             close (fd);
  725.             fprintf ( stderr, "\n\n");
  726.             return;
  727.         }
  728.  
  729.         switch (state) {
  730.         case 0: /* A */
  731.             if ( index + BF >= stop )
  732.                 index += feed (fd, A+index, stop-index );
  733.             else
  734.                 index += feed (fd, A+index, BF );
  735.             break;
  736.  
  737.         case 1: /* B */
  738.             if ( index + BF >= stop )
  739.                 index += feed (fd, B+index, stop-index );
  740.             else
  741.                 index += feed (fd, B+index, BF );
  742.             break;
  743.  
  744.         case 2: /* B => A */
  745.             if ( index + BF >= stop )
  746.                 index += feed2 (fd, B+index, A+index, stop-index );
  747.             else
  748.                 index += feed2 (fd, B+index, A+index, BF );
  749.             state = 0;
  750.             break;
  751.  
  752.         case 3: /* A => B */
  753.             if ( index + BF >= stop )
  754.                 index += feed2 (fd, A+index, B+index, stop-index );
  755.             else
  756.                 index += feed2 (fd, A+index, B+index, BF );
  757.             state = 1;
  758.             break;
  759.             
  760.         case 4: /* A */
  761.             strcpy ( message, "A  " );
  762.             if ( index + BF >= stop )
  763.                 index += feed (fd, A+index, stop-index ),
  764.                 state++;
  765.             else
  766.                 index += feed (fd, A+index, BF );
  767.             break;
  768.  
  769.         case 5: /* B */
  770.             strcpy ( message, "  B" );
  771.             if ( index + BF >= stop )
  772.                 index += feed (fd, B+index, stop-index ),
  773.                 state--;
  774.             else
  775.                 index += feed (fd, B+index, BF );
  776.             break;
  777.  
  778.         case 6: /* X */
  779.             strcpy ( message, " X " );
  780.             if ( index + BF >= stop )
  781.                 index += feed (fd, (rnd ? B : A)+index, stop-index ),
  782.                 state++;
  783.             else
  784.                 index += feed (fd, (rnd ? B : A)+index, BF );
  785.             break;
  786.  
  787.         case 7: /* !X */
  788.             strcpy ( message, "!X " );
  789.             if ( index + BF >= stop )
  790.                 index += feed (fd, (rnd ? A : B)+index, stop-index ),
  791.                 state--;
  792.             else
  793.                 index += feed (fd, (rnd ? A : B)+index, BF );
  794.             break;
  795.  
  796.         case 8:
  797.             if ( index + BF/2 >= stop )
  798.                 index += feed2 (fd, A+index, B+index, stop-index );
  799.             else
  800.                 index += feed2 (fd, A+index, B+index, BF/2 );
  801.             Message ( "  B", index, freq, start, stop );
  802.             if ( index + BF >= stop )
  803.                 index += feed (fd, B+index, stop-index );
  804.             else
  805.                 index += feed (fd, B+index, BF );
  806.             if ( index + BF/2 >= stop )
  807.                 index += feed2 (fd, B+index, A+index, stop-index );
  808.             else
  809.                 index += feed2 (fd, B+index, A+index, BF/2 );
  810.             Message ( "A  ", index, freq, start, stop );
  811.             if ( index + BF >= stop )
  812.                 index += feed (fd, A+index, stop-index );
  813.             else
  814.                 index += feed (fd, A+index, BF );
  815.             break;
  816.  
  817.         case 9: /* Liko */
  818.             if ( index + BF >= stop )
  819.                 index += feedfac (fd, A+index, B+index, stop-index, fac1, fac2 );
  820.             else
  821.                 index += feedfac (fd, A+index, B+index, BF        , fac1, fac2 );
  822.             break;
  823.             
  824.         default:
  825.             assert (0);
  826.         }
  827.  
  828.         if (index >= stop)
  829.             index = start;
  830.         Message ( message, calc_true_index ( index, start, stop), freq, start, stop );
  831.     }
  832. }
  833.  
  834.  
  835. int  has_ext ( const char* name, const char* ext )
  836. {
  837.     if ( strlen (name) < strlen (ext) )
  838.         return 0;
  839.     name += strlen (name) - strlen (ext);
  840.     return strcasecmp (name, ext)  ?  0  :  1;
  841. }
  842.  
  843.  
  844. typedef struct {
  845.     const char* const  extention;
  846.     const char* const  command;
  847. } decoder_t;
  848.  
  849.  
  850. #define REDIR     " 2> /dev/null"
  851. #define STDOUT    "/dev/fd/1"
  852.  
  853. const decoder_t  decoder [] = {
  854.     { ".mp1"    , "/usr/local/bin/mpg123 -w - %s"                   REDIR },  // MPEG Layer I         : www.iis.fhg.de, www.mpeg.org
  855.     { ".mp2"    , "/usr/local/bin/mpg123 -w - %s"                   REDIR },  // MPEG Layer II        : www.iis.fhg.de, www.uq.net.au/~zzmcheng, www.mpeg.org
  856.     { ".mp3"    , "/usr/local/bin/mpg123 -w - %s"                   REDIR },  // MPEG Layer III       : www.iis.fhg.de, www.mp3dev.org/mp3, www.mpeg.org
  857.     { ".mpt"    , "/usr/local/bin/mpg123 -w - %s"                   REDIR },  // MPEG Layer III       : www.iis.fhg.de, www.mp3dev.org/mp3, www.mpeg.org
  858.     { ".mpp"    , "/usr/local/bin/mppdec %s -"                      REDIR },  // MPEGplus             : www.stud.uni-hannover.de/user/73884
  859.     { ".mp+"    , "/usr/local/bin/mppdec %s -"                      REDIR },  // MPEGplus             : www.stud.uni-hannover.de/user/73884
  860.     { ".aac"    , "/usr/local/bin/faad -t.wav -w %s"                REDIR },  // Advanced Audio Coding: psytel.hypermart.net, www.aac-tech.com, sourceforge.net/projects/faac, www.aac-audio.com, www.mpeg.org
  861.     { "aac.lqt" , "/usr/local/bin/faad -t.wav -w %s"                REDIR },  // Advanced Audio Coding: psytel.hypermart.net, www.aac-tech.com, sourceforge.net/projects/faac, www.aac-audio.com, www.mpeg.org
  862.     { ".ac3"    , "/usr/local/bin/ac3dec %s"                        REDIR },  // Dolby AC3            : www.att.com
  863.     { "ac3.lqt" , "/usr/local/bin/ac3dec %s"                        REDIR },  // Dolby AC3            : www.att.com
  864.     { ".ogg"    , "/usr/local/bin/ogg123 -d wav -o file:"STDOUT" %s"REDIR },  // Ogg Vorbis           : www.xiph.org/ogg/vorbis/index.html
  865.     { ".pac"    , "/usr/local/bin/lpac -x %s "STDOUT                REDIR },  // Lossless predictive Audio Compression: www-ft.ee.tu-berlin.de/~liebchen/lpac.html (liebchen@ft.ee.tu-berlin.de)
  866.     { ".shn"    , "/usr/local/bin/shorten -x < %s"                  REDIR },  // Shorten              : shnutils.freeshell.org, www.softsound.com/Shorten.html (shnutils@freeshell.org, shorten@softsound.com)
  867.     { ".wav.gz" , "gzip  -d < %s | sox -twav - -twav -sw -"         REDIR },  // gziped WAV
  868.     { ".wav.sz" , "szip  -d < %s | sox -twav - -twav -sw -"         REDIR },  // sziped WAV
  869.     { ".wav.sz2", "szip2 -d < %s | sox -twav - -twav -sw -"         REDIR },  // sziped WAV
  870.     { ".raw"    , "sox -r44100 -sw -c2 -traw %s -twav -sw -"        REDIR },  // raw files are treated as CD like audio
  871.     { ".rm"     , "echo %s '???'"                                   REDIR },  // Real Audio           : www.real.com
  872.     { ".epc"    , "echo %s '???'"                                   REDIR },  // ePAC                 : www.audioveda.com, www.lucent.com/ldr
  873.     { ".mov"    , "echo %s '???'"                                   REDIR },  // QDesign Music 2      : www.qdesign.com
  874.     { ".vqf"    , "echo %s '???'"                                   REDIR },  // TwinVQ               : www.yamaha-xg.com/english/xg/SoundVQ, www.vqf.com, sound.splab.ecl.ntt.co.jp/twinvq-e
  875.     { ".wma"    , "echo %s '???'"                                   REDIR },  // Microsoft Media Audio: www.windowsmedia.com, www.microsoft.com/windows/windowsmedia
  876.     { ".ape"    , "echo %s '???'"                                   REDIR },  // Monkey's Audio Codec : www.monkeysaudio.com (email@monkeysaudio.com)
  877.     { ".rka"    , "/opt/winapp/rkau -d %s"                          REDIR },  // RK Audio:              
  878.     { ".mod"    , "xmp -b16 -c -f44100 --stereo -o- %s | sox -r44100 -sw -c2 -traw - -twav -sw -"
  879.                                                                     REDIR },  // Amiga's Music on Disk:
  880.     { ""        , "sox %s -twav -sw -"                              REDIR },  // Rest, may be possible with sox
  881. };
  882.  
  883. #undef REDIR
  884. #undef STDOUT
  885.  
  886.  
  887. int  readwave ( stereo_t* buff, size_t maxlen, const char* name, size_t* len )
  888. {
  889.     char*           command = malloc (2*strlen(name) + 512);
  890.     char*           name_q  = malloc (2*strlen(name) + 128);
  891.     unsigned short  header [22];
  892.     FILE*           fp;
  893.     size_t          i;
  894.     size_t          j;
  895.  
  896.     // The *nice* shell quoting
  897.     i = j = 0;
  898.     if ( name[i] == '-' )
  899.         name_q[j++] = '.',
  900.         name_q[j++] = '/';
  901.         
  902.     while (name[i]) {
  903.         if ( !isalnum (name[i]) && name[i]!='-' && name[i]!='_' && name[i]!='.' )
  904.             name_q[j++] = '\\';
  905.         name_q[j++] = name[i++];
  906.     }
  907.     name_q[j] = '\0';
  908.  
  909.     fprintf (stderr, "Reading %s", name );
  910.     for ( i = 0; i < sizeof(decoder)/sizeof(*decoder); i++ )
  911.         if ( has_ext (name, decoder[i].extention) ) {
  912.             sprintf ( command, decoder[i].command, name_q );
  913.             break;
  914.         }
  915.  
  916.     free (name_q);
  917.     if ( (fp = popen (command, "r")) == NULL ) {
  918.         fprintf (stderr, "Can't exec:\n%s\n", command );
  919.         exit (1);
  920.     }
  921.     free (command);
  922.     
  923.     fprintf (stderr, " ..." );
  924.     fread ( header, sizeof(*header), sizeof(header)/sizeof(*header), fp );
  925.     switch ( header[11] ) {
  926.         case 2:
  927.             *len = fread ( buff, sizeof(stereo_t), maxlen, fp );
  928.             break;
  929.         case 1:
  930.             *len = fread ( buff, sizeof(sample_t), maxlen, fp );
  931.             for ( i = *len; i-- > 0; )
  932.                 buff[i][0] = buff[i][1] = ((sample_t*)buff) [i];
  933.             break;
  934.         case 0:
  935.             fprintf (stderr, "\b\b\b\b, Standard Open Source Bug detected, try murksaround ..." );
  936.             *len = fread ( buff, sizeof(stereo_t), maxlen, fp );
  937.             header[11] =     2;
  938.             header[12] = 65534;  /* use that of the other channel */
  939.             break;
  940.         default:
  941.             fprintf (stderr, "Only 1 or 2 channels are supported, not %u\n", header[11] );
  942.             pclose (fp);
  943.             return -1;
  944.     }
  945.     pclose ( fp ); 
  946.     fprintf (stderr, "\n" );
  947.     return header[12] ? header[12] : 65534;
  948. }
  949.  
  950.  
  951. double  cross_analyze ( const stereo_t* p1, const stereo_t *p2, size_t len )
  952. {
  953.     float   P1 [MAX] [2];
  954.     float   P2 [MAX] [2];
  955.     int     i;
  956.     int     maxindex;
  957.     double  sum1;
  958.     double  sum2;
  959.     double  max;
  960.     double  y1;
  961.     double  y2;
  962.     double  y3;
  963.     double  yo;
  964.     double  xo;
  965.     double  tmp;
  966.     double  tmp1;
  967.     double  tmp2;
  968.     int     ret = 0;
  969.     int     cnt = 5;
  970.  
  971.     // Calculating effective voltage
  972.     sum1 = sum2 = 0.;
  973.     for ( i = 0; i < len; i++ ) {
  974.         sum1 += (double)p1[i][0] * p1[i][0];
  975.         sum2 += (double)p2[i][0] * p2[i][0];
  976.     }
  977.     sum1 = sqrt ( sum1/len );
  978.     sum2 = sqrt ( sum2/len );
  979.  
  980.     // Searching beginning of signal (not stable for pathological signals)
  981.     for ( i = 0; i < len; i++ )
  982.         if ( abs (p1[i][0]) >= sum1  &&  abs (p2[i][0]) >= sum2 )
  983.             break;
  984.     p1  += i;
  985.     p2  += i;
  986.     len -= i;
  987.  
  988.     if ( len <= MAX )
  989.         return 0;
  990.  
  991.     // Filling arrays for FFT
  992.     do {
  993.         sum1 = sum2 = 0.;
  994.         for ( i = 0; i < MAX; i++ ) {
  995. #ifdef USEDIFF
  996.             tmp1  = p1 [i][0] - p1 [i+1][0];
  997.             tmp2  = p2 [i+ret][0] - p2 [i+ret+1][0];
  998. #else
  999.             tmp1  = p1 [i][0];
  1000.             tmp2  = p2 [i+ret][0];
  1001. #endif
  1002.             sum1 += tmp1*tmp1;
  1003.             sum2 += tmp2*tmp2;
  1004.             P1 [i][0] = tmp1;
  1005.             P2 [i][0] = tmp2;
  1006.             P1 [i][1] = 0.;
  1007.             P2 [i][1] = 0.;
  1008.         }
  1009.  
  1010.         fft (P1, MAX);
  1011.         fft (P2, MAX);
  1012.  
  1013.         for ( i = 0; i < MAX; i++ ) {
  1014.             double  a0 = P1 [i][0];
  1015.             double  a1 = P1 [i][1];
  1016.             double  b0 = P2 [(MAX-i)&(MAX-1)][0];
  1017.             double  b1 = P2 [(MAX-i)&(MAX-1)][1];
  1018.             P1 [i][0] = a0*b0 - a1*b1;
  1019.             P1 [i][1] = a0*b1 + a1*b0;
  1020.         }
  1021.  
  1022.         fft (P1, MAX);
  1023.  
  1024.         max = P1 [maxindex = 0][0];
  1025.         for ( i = 1; i < MAX; i++ )
  1026.             if ( P1[i][0] > max )
  1027.                 max = P1 [maxindex = i][0];
  1028.  
  1029.         y2 = P1 [ maxindex           ][0];
  1030.         y1 = P1 [(maxindex-1)&(MAX-1)][0] - y2;
  1031.         y3 = P1 [(maxindex+1)&(MAX-1)][0] - y2;
  1032.  
  1033.         xo = 0.5 * (y1-y3) / (y1+y3);
  1034.         yo = 0.5 * ( (y1+y3)*xo + (y3-y1) ) * xo;
  1035.  
  1036.         if (maxindex > MAX/2 )
  1037.             maxindex -= MAX;
  1038.  
  1039.         ret += maxindex;
  1040.         tmp = 100./MAX/sqrt(sum1*sum2);
  1041.         if (verbose)
  1042.             printf ( "[%5d]%8.4f  [%5d]%8.4f  [%5d]%8.4f  [%10.4f]%8.4f\n",
  1043.                      ret- 1, (y1+y2)*tmp,
  1044.                      ret   ,     y2 *tmp,
  1045.                      ret+ 1, (y3+y2)*tmp,
  1046.                      ret+xo, (yo+y2)*tmp );
  1047.  
  1048.     } while ( maxindex  &&  cnt-- );
  1049.  
  1050.     return ret + xo;
  1051. }
  1052.  
  1053.  
  1054. short  to_short ( int x )
  1055. {
  1056.     return x == (short)x  ?  (short)x  :  (short) ((x >> 31) ^ 0x7FFF);
  1057. }
  1058.  
  1059.  
  1060. void  DC_cancel ( stereo_t* p, size_t len )
  1061. {
  1062.     double  sum1 = 0;
  1063.     double  sum2 = 0;
  1064.     size_t  i;
  1065.     int     diff1;
  1066.     int     diff2;
  1067.     
  1068.     for (i = 0; i < len; i++ ) {
  1069.         sum1 += p[i][0];
  1070.         sum2 += p[i][1];
  1071.     }
  1072.     if ( fabs(sum1) < len  &&  fabs(sum2) < len )
  1073.         return;
  1074.         
  1075.     diff1 = round ( sum1 / len );
  1076.     diff2 = round ( sum2 / len );
  1077.     if (verbose)
  1078.         fprintf (stderr, "Removing DC (left=%d, right=%d)\n", diff1, diff2 );
  1079.     
  1080.     for (i = 0; i < len; i++ ) {
  1081.         p[i][0] = to_short (p[i][0] + diff1);
  1082.         p[i][1] = to_short (p[i][1] + diff2);
  1083.     }
  1084. }
  1085.  
  1086. void  multiply ( char c, stereo_t* p, size_t len, double fact )
  1087. {
  1088.     size_t  i;
  1089.     
  1090.     if ( fact == 1. )
  1091.         return;
  1092.     if (verbose)
  1093.         fprintf (stderr, "Multiplying %c by %7.5f\n", c, fact );
  1094.     
  1095.     for (i = 0; i < len; i++ ) {
  1096.         p[i][0] = to_short (p[i][0] * fact );
  1097.         p[i][1] = to_short (p[i][1] * fact );
  1098.     }
  1099. }
  1100.  
  1101.  
  1102. int  maximum ( stereo_t* p, size_t len )
  1103. {
  1104.     int     max = 0;
  1105.     size_t  i;
  1106.     
  1107.     for (i = 0; i < len; i++ ) {
  1108.         if (abs(p[i][0]) > max) max = abs(p[i][0]);
  1109.         if (abs(p[i][1]) > max) max = abs(p[i][1]);
  1110.     }
  1111.     return max;
  1112. }
  1113.  
  1114.  
  1115. void  usage ( void )
  1116. {
  1117.     fprintf ( stderr, 
  1118.         "usage:  abx [-v] File_A File_B\n"
  1119.         "\n"
  1120.         "File_A and File_B loaded and played. File_A should be the better/reference\n"
  1121.         "file, File_B the other. You can press the following keys:\n"
  1122.         "\n"
  1123.         "  a/A:    Listen to File A\n"
  1124.         "  b/B:    Listen to File B\n"
  1125.         "  x/X:    Listen to the randomly selected File X, which is A or B\n"
  1126.         "  Ctrl-A: You vote for X=A\n"
  1127.         "  Ctrl-B: You vote for X=B\n"
  1128.         "  m:      Alternating playing A and B. Fast switching\n"
  1129.         "  M:      Alternating playing A and B. Slow switching\n"
  1130.         "  d/D/Ctrl-D/Alt-d/Alt-D:\n"
  1131.         "          Listen to the difference A-B (+0 dB...+40 dB)\n"
  1132.         "  o/p:    Chunk select\n"
  1133.         "  hjkl:   Chunk fine adjust (hj: start, kl: stop)\n"
  1134.         "  Space:  Chunk deselect\n"
  1135.         "  0...9:  Listen to B, but difference A-B is amplified by 0-9 dB\n"
  1136.         "  Q:      Quit the program\n"
  1137.         "\n"
  1138.     );
  1139. }
  1140.  
  1141.  
  1142. int  main ( int argc, char** argv )
  1143. {
  1144.     stereo_t*  _A = calloc ( sizeof(stereo_t), MAX_LEN );
  1145.     stereo_t*  _B = calloc ( sizeof(stereo_t), MAX_LEN );
  1146.     stereo_t*  A  = _A;
  1147.     stereo_t*  B  = _B;
  1148.     size_t     len_A;
  1149.     size_t     len_B;
  1150.     size_t     len;
  1151.     int        max_A;
  1152.     int        max_B;
  1153.     int        max;
  1154.     long       freq1;
  1155.     long       freq2;
  1156.     int        shift;
  1157.     double     fshift;
  1158.     double     ampl;
  1159.     int        ampl_X;
  1160.     korr_t     k;
  1161.     
  1162.     if (argc > 1  &&  0 == strcmp (argv[1], "-v") ) {
  1163.         verbose = 1;
  1164.         argc--;
  1165.         argv++;
  1166.     }
  1167.  
  1168.     switch ( argc ) {
  1169.     case 0:
  1170.     case 1:
  1171.     case 2:
  1172.     default:
  1173.         usage ();
  1174.         return 1;
  1175.     case 3:
  1176.         usage();
  1177.         break;
  1178.     }
  1179.  
  1180.     freq1 = readwave ( A, MAX_LEN, argv[1], &len_A );
  1181.     DC_cancel ( A, len_A );
  1182.     freq2 = readwave ( B, MAX_LEN, argv[2], &len_B );
  1183.     DC_cancel ( B, len_B );
  1184.     
  1185.     if      ( freq1 == 65534  &&  freq2 != 65534 )
  1186.         freq1 = freq2;
  1187.     else if ( freq2 == 65534  &&  freq1 != 65534 )
  1188.         freq2 = freq1;
  1189.     else if ( freq1 == 65534  &&  freq2 == 65534 )
  1190.         freq1 = freq2 = 44100;
  1191.  
  1192.     if ( freq1 != freq2 ) {
  1193.         fprintf ( stderr, "Different sample frequencies currently not supported\n");
  1194.         fprintf ( stderr, "A: %ld, B: %ld\n", freq1, freq2 );
  1195.         return 2;
  1196.     }
  1197.  
  1198.     len    = len_A < len_B  ?  len_A  :  len_B;
  1199.     fshift = cross_analyze ( A, B, len );
  1200.     shift  = floor ( fshift + 0.5 );
  1201.  
  1202.     if ( verbose ) {
  1203.         fprintf ( stderr, "Delay Ch1 is %.4f samples\n", fshift );
  1204.         fprintf ( stderr, "Delay Ch2 is %.4f samples\n", 
  1205.                   cross_analyze ( (stereo_t*)(((sample_t*)A)+1), (stereo_t*)(((sample_t*)B)+1), len ) );
  1206.     }
  1207.  
  1208.     if (shift > 0) {
  1209.         if (verbose) 
  1210.             fprintf ( stderr, "Delaying A by %d samples\n", +shift);
  1211.         B     += shift;
  1212.         len_B -= shift;
  1213.     }
  1214.     if (shift < 0) {
  1215.         if (verbose)
  1216.             fprintf ( stderr, "Delaying B by %d samples\n", -shift);
  1217.         A     -= shift;
  1218.         len_A += shift;
  1219.     }
  1220.  
  1221.     len    = len_A < len_B  ?  len_A  :  len_B;
  1222.     memset ( &k, 0, sizeof(k) );    
  1223.     analyze_stereo ( A, B, len, &k );
  1224.     ampl  = report (&k);
  1225.     max_A = maximum ( A, len ); 
  1226.     max_B = maximum ( B, len ); 
  1227.     
  1228.     if ( ampl <= 0.98855 ) { /* < -0.05 dB */
  1229.         max    = max_A*ampl < max_B  ?  max_B  :  max_A*ampl;
  1230.         ampl_X = (int)(29203 / max);
  1231.         if ( ampl_X < 2 ) ampl_X = 1;
  1232.         multiply ( 'A', A, len, ampl*ampl_X );
  1233.         multiply ( 'B', B, len,      ampl_X );
  1234.     } else if ( ampl >= 1.01158 ) { /* > +0.05 dB */
  1235.         max    = max_A < max_B/ampl  ?  max_B/ampl  :  max_A;
  1236.         ampl_X = (int)(29203 / max);
  1237.         if ( ampl_X < 2 ) ampl_X = 1;
  1238.         multiply ( 'A', A, len,         ampl_X );
  1239.         multiply ( 'B', B, len, 1./ampl*ampl_X );
  1240.     } else {
  1241.         max    = max_A < max_B ? max_B : max_A;
  1242.         ampl_X = (int)(29203 / max);
  1243.         if ( ampl_X < 2 ) ampl_X = 1;
  1244.         multiply ( 'A', A, len, ampl_X );
  1245.         multiply ( 'B', B, len, ampl_X );
  1246.     }
  1247.  
  1248.     set ();
  1249.     nice (-20);
  1250.     testing ( A, B, len, freq1 );
  1251.     reset ();
  1252.  
  1253.     free (_A);
  1254.     free (_B);
  1255.     return 0;
  1256. }
  1257.  
  1258. /* end of abx.c */
  1259.